'use strict';
let fs = require('fs');
let path = require('path');
let bbbrecordsreg = /.+?-(\d{13})$/i;
let xml2js = require('xml2js');
let async = require('async');
let _ = require('lodash');
let debug = require('debug')('bbb:record:search');
let filter = require('./filter');
let originMetadata = {
    "recording": {
        "id": "",
        "state": "published",
        "published": "true",
        "start_time": "0",
        "end_time": "0",
        "participants": "0",
        "meeting": {
            "id": "",
            "externalId": "",
            "name": "",
            "breakout": "false"
        },
        "meta": {
            "bbb-context": "",
            "bbb-recording-description": "",
            "bbb-origin-server-common-name": "",
            "meetingName": "",
            "bbb-origin-server-name": "",
            "bbb-origin-version": "",
            "bbb-origin": "",
            "bbb-origin-tag": "",
            "meetingId": "",
            "bbb-recording-tags": "",
            "bbb-recording-name": "",
            "isBreakout": "false"
        },
        "playback": {
            "format": "presentation",
            "link": "",
            "processing_time": "0",
            "duration": "0",
            "extensions": {
                "preview": {
                    "images": {
                        "image": []
                    }
                }
            }
        }
    }
};

// 获取所有目录
function readdir(dirpath, filter) {
    return new Promise(function(resolve, reject) {
        fs.readdir(dirpath, function(err, files) {
            if (err) {
                resolve([]);
            } else {
                resolve(files);
            }
        });
    }).then(function(files) {
        let dirs = [];
        let nextpaths = [];
        files.forEach(function(file) {
            if (bbbrecordsreg.test(file)) {
                let push = filter ? filter(RegExp.$1, file, dirpath) : true;
                if (push) {
                    dirs.push(path.join(dirpath, file));
                }
            } else {
                nextpaths.push(path.join(dirpath, file));
            }
        });
        let childdirs = nextpaths.map(function(file) {
            return new Promise(function(resolve, reject) {
                fs.stat(file, function(err, stats) {
                    if (!err && stats.isDirectory()) {
                        readdir(file, filter).then(function(rts) {
                            resolve(rts);
                        });
                    } else {
                        resolve([]);
                    }
                });
            });
        });
        return Promise.all(childdirs).then(function(files) {
            files.forEach(function(item) {
                dirs = dirs.concat(item);
            });
            return dirs;
        });
    });
}

function loadMetadata(options, cb) {
    let recordsPath = options && options.path || '';
    let filter = options && options.dirFilter || null;
    readdir(recordsPath, filter).then(function(records) {
        debug(`共查找到${records.length}条信息`);
        async.mapSeries(records, function(item, cb) {
            let xmlpath = path.join(item, options.dataFileName);
            options.readFile.call(xmlpath, xmlpath, function(err, data) {
                if (err) {
                    return cb(err);
                }
                options.parseXML.call(xmlpath, data, function(err, obj) {
                    if (err) {
                        return cb(`文件[${xmlpath}]转换失败：${err}`);
                    }
                    obj.dirPath = item;
                    cb(null, obj);
                });
            });
        }, cb);
    });
}

function readFile(xmlpath, cb) {
    fs.readFile(xmlpath, function(err, data) {
        if (err) {
            cb(`文件[${xmlpath}]读取失败：${err.message}`, null);
        } else {
            cb(null, data);
        }
    });
}

function parseMetadata(xml, cb) {
    try {
        xml2js.parseString(xml, {mergeAttrs: true, explicitArray: false, emptyTag: undefined}, function(err, result) {
            if (err) {
                cb(err, null);
                return;
            }
            let copy = _.defaultsDeep({}, result, originMetadata);
            cb(null, copy);
        })
    } catch (e) {
        cb(e.message);
    }
}

function search(options, cb) {
    cb=cb||function() {
        let callback;
        let promise = new Promise(function(resolve, reject) {
            callback = function(err, data) {
                if (err) return reject(err);
                return resolve(data);
            };
        });
        callback.promise = promise;
        return callback;
    }
    let opts = {
        readFile: readFile,
        path: '',//搜索的文件夹名
        dirFilters: [],//文件夹过滤函数，
        dataFileName: 'metadata.xml',//需要转换的xml文件名
        where: {domain: '', name: '', start: '', end: '', courses: ''}, //内部默认的过滤处理
        filters: [], //过滤方法 会传递数据对象
        parseXML: parseMetadata, // xml文件转换函数
    };

    opts = _.defaultsDeep({}, {originMetadata}, options, opts);
    let dirFilter = opts.dirFilters;
    let where = opts.where;
    if (where.start) {
        dirFilter.push(filter.timeFilter(where.start, 'gt'));
    }
    if (where.end) {
        dirFilter.push(filter.timeFilter(where.end, 'lt'));
    }

    opts.dirFilter = filter.Filters(dirFilter);

    let modelFilter = opts.filters;
    if (where.domain) {
        modelFilter.push(filter.domainFilter(where.domain));
    }
    if (where.name) {
        modelFilter.push(filter.nameFilter(where.name));
    }
    if (where.courses) {
        modelFilter.push(filter.coursesFilter(where.courses));
    }
    let modelFilters = filter.Filters(modelFilter);
    loadMetadata(opts, function(err, result) {
        let rts = result.filter(function(item) {
            if (!item) {
                return false;
            }
            return modelFilters(item);
        });
        debug(`错误信息:`, err);
        debug(`查找记录返回结果[${rts.length}]条。`);
        cb(null, rts);
    });
}

module.exports.readdir = readdir;
module.exports.loadMetadata = loadMetadata;
module.exports.search = search;
